# -*- coding: utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt
from datetime import datetime, timedelta
import tkinter as tk
from tkinter import ttk, messagebox
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
import matplotlib
from mpl_toolkits.mplot3d import Axes3D
matplotlib.use('TkAgg')

# 设置中文显示
plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False


class CometBrightnessApp:
    def __init__(self, root):
        self.root = root
        self.root.title("彗星亮度预测工具 v4.0")
        self.root.geometry("1400x900")

        # 行星轨道半径 (AU)
        self.planet_orbits = {
            '水星': 0.39,
            '金星': 0.72,
            '地球': 1.00,
            '火星': 1.52,
            '木星': 5.20,
            '土星': 9.58,
            '天王星': 19.22,
            '海王星': 30.05
        }

        # 行星颜色
        self.planet_colors = {
            '水星': 'gray',
            '金星': 'gold',
            '地球': 'blue',
            '火星': 'red',
            '木星': 'orange',
            '土星': 'goldenrod',
            '天王星': 'lightblue',
            '海王星': 'blue'
        }

        # 初始化变量
        self.current_dates = None
        self.orbit_m_pred = None
        self.obs_m_pred = None
        self.r_pred = None
        self.delta_pred = None
        self.orbit_points = None
        self.sun_pos = np.array([0, 0, 0])

        # 子窗口引用
        self.chart_window = None
        self.orbit_window = None

        # 设置UI
        self.setup_ui()
        self.fill_sample_data()

    def setup_ui(self):
        """设置用户界面 - 三栏等宽布局"""
        # 主框架
        main_frame = ttk.Frame(self.root, padding="10")
        main_frame.pack(fill=tk.BOTH, expand=True)

        # 配置三栏等宽
        main_frame.columnconfigure(0, weight=1, uniform="equal")
        main_frame.columnconfigure(1, weight=1, uniform="equal")
        main_frame.columnconfigure(2, weight=1, uniform="equal")

        # 左侧控制区域
        left_frame = ttk.LabelFrame(main_frame, text="彗星参数设置", padding="10")
        left_frame.grid(row=0, column=0, sticky="nsew", padx=(0, 5))

        # 中间结果显示区域
        middle_frame = ttk.LabelFrame(main_frame, text="预测结果", padding="10")
        middle_frame.grid(row=0, column=1, sticky="nsew", padx=5)

        # 右侧控制区域
        right_frame = ttk.LabelFrame(
            main_frame, text="预测控制与轨道模拟", padding="10")
        right_frame.grid(row=0, column=2, sticky="nsew", padx=(5, 0))

        # 设置行权重使内容均匀分布
        main_frame.rowconfigure(0, weight=1)

        # 左侧栏内容
        self.setup_left_frame(left_frame)

        # 中间栏内容
        self.setup_middle_frame(middle_frame)

        # 右侧栏内容
        self.setup_right_frame(right_frame)

    def setup_left_frame(self, parent):
        """设置左侧栏内容"""
        # 窗口控制
        window_frame = ttk.LabelFrame(parent, text="窗口控制", padding="10")
        window_frame.pack(fill=tk.X, pady=5)

        ttk.Button(window_frame, text="打开图表窗口",
                   command=self.open_chart_window).pack(pady=5)
        ttk.Button(window_frame, text="打开轨道窗口",
                   command=self.open_orbit_window).pack(pady=5)
        ttk.Button(window_frame, text="关闭所有窗口",
                   command=self.close_all_windows).pack(pady=5)

        # 彗星选择
        comet_frame = ttk.LabelFrame(parent, text="彗星选择", padding="10")
        comet_frame.pack(fill=tk.X, pady=5)

        ttk.Label(comet_frame, text="选择彗星:").grid(
            row=0, column=0, padx=5, pady=2, sticky=tk.W)
        self.comet_var = tk.StringVar()
        comet_combo = ttk.Combobox(
            comet_frame, textvariable=self.comet_var, width=25)
        comet_combo['values'] = (
            "323P-B/SOHO",
            "240P/NEAT",
            "24P/Schaumasse",
            "C/2025 A6 (Lemmon)",
            "C/2025 R2 (SWAN)",
            "C/2025 K1 (ATLAS)"
        )
        comet_combo.grid(row=0, column=1, padx=5, pady=2)
        comet_combo.bind('<<ComboboxSelected>>', self.on_comet_selected)

        # 彗星信息
        info_frame = ttk.LabelFrame(parent, text="彗星信息", padding="10")
        info_frame.pack(fill=tk.X, pady=5)

        ttk.Label(info_frame, text="彗星名称:").grid(
            row=0, column=0, padx=5, pady=2, sticky=tk.W)
        self.name_entry = ttk.Entry(info_frame, width=25)
        self.name_entry.grid(row=0, column=1, padx=5, pady=2)

        # 轨道元素
        orbit_frame = ttk.LabelFrame(
            parent, text="轨道元素 (来源: MPC星历表服务)", padding="10")
        orbit_frame.pack(fill=tk.X, pady=5)

        orbit_params = [
            ("q (近日点距离 AU)", "perihelion_distance"),
            ("a (半长轴 AU)", "semi_major_axis"),
            ("e (偏心率)", "eccentricity"),
            ("ω (近日点幅角 °)", "arg_perihelion"),
            ("Ω (升交点赤经 °)", "long_asc_node"),
            ("i (轨道倾角 °)", "inclination"),
            ("P (轨道周期 年)", "orbital_period"),
            ("T (近日点时间)", "perihelion_time"),
            ("历元时间", "epoch_time")
        ]

        self.orbit_entries = {}
        for i, (label, key) in enumerate(orbit_params):
            ttk.Label(orbit_frame, text=label).grid(
                row=i, column=0, padx=5, pady=1, sticky=tk.W)
            entry = ttk.Entry(orbit_frame, width=15)
            entry.grid(row=i, column=1, padx=5, pady=1)
            self.orbit_entries[key] = entry

        # 星等参数
        mag_frame = ttk.LabelFrame(parent, text="星等参数", padding="10")
        mag_frame.pack(fill=tk.X, pady=5)

        ttk.Label(mag_frame, text="轨道计算 H:").grid(
            row=0, column=0, padx=5, pady=2, sticky=tk.W)
        self.orbit_H_entry = ttk.Entry(mag_frame, width=10)
        self.orbit_H_entry.grid(row=0, column=1, padx=5, pady=2)

        ttk.Label(mag_frame, text="轨道计算 n:").grid(
            row=1, column=0, padx=5, pady=2, sticky=tk.W)
        self.orbit_n_entry = ttk.Entry(mag_frame, width=10)
        self.orbit_n_entry.grid(row=1, column=1, padx=5, pady=2)

        ttk.Label(mag_frame, text="观测拟合 H:").grid(
            row=0, column=2, padx=5, pady=2, sticky=tk.W)
        self.obs_H_entry = ttk.Entry(mag_frame, width=10)
        self.obs_H_entry.grid(row=0, column=3, padx=5, pady=2)

        ttk.Label(mag_frame, text="观测拟合 n:").grid(
            row=1, column=2, padx=5, pady=2, sticky=tk.W)
        self.obs_n_entry = ttk.Entry(mag_frame, width=10)
        self.obs_n_entry.grid(row=1, column=3, padx=5, pady=2)

    def setup_middle_frame(self, parent):
        """设置中间栏内容"""
        # 创建滚动区域
        canvas = tk.Canvas(parent)
        scrollbar = ttk.Scrollbar(
            parent, orient="vertical", command=canvas.yview)
        scrollable_frame = ttk.Frame(canvas)

        scrollable_frame.bind(
            "<Configure>",
            lambda e: canvas.configure(scrollregion=canvas.bbox("all"))
        )

        canvas.create_window((0, 0), window=scrollable_frame, anchor="nw")
        canvas.configure(yscrollcommand=scrollbar.set)

        canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)

        # 结果显示
        self.info_labels = {}
        result_data = [
            ("轨道类型", "待计算"),
            ("轨道计算最亮星等", "待计算"),
            ("轨道计算最亮日期", "待计算"),
            ("观测拟合最亮星等", "待计算"),
            ("观测拟合最亮日期", "待计算"),
            ("近日点日期", "待计算"),
            ("亮度差异", "待计算"),
            ("预测总天数", "待计算"),
            ("近地点距离", "待计算"),
            ("今日轨道计算星等", "待计算"),
            ("今日观测拟合星等", "待计算"),
            ("今日日彗距", "待计算"),
            ("今日地彗距", "待计算"),
            ("彗发长度 (km)", "待计算"),
            ("彗发长度 (°)", "待计算"),
            ("彗尾长度 (km)", "待计算"),
            ("彗尾长度 (°)", "待计算")
        ]

        for i, (label, value) in enumerate(result_data):
            frame = ttk.Frame(scrollable_frame)
            frame.pack(fill=tk.X, pady=2)

            ttk.Label(frame, text=label + ":", width=20,
                      anchor="e").pack(side=tk.LEFT, padx=5)
            value_label = ttk.Label(frame, text=value, width=20, anchor="w")
            value_label.pack(side=tk.LEFT, padx=5)
            self.info_labels[label] = value_label

    def setup_right_frame(self, parent):
        """设置右侧栏内容"""
        # 预测控制
        pred_frame = ttk.LabelFrame(parent, text="预测控制", padding="10")
        pred_frame.pack(fill=tk.X, pady=5)

        self.pred_mode = tk.StringVar(value="days")

        ttk.Radiobutton(pred_frame, text="按天数预测", variable=self.pred_mode,
                        value="days").pack(side=tk.LEFT, padx=5)
        ttk.Radiobutton(pred_frame, text="按日期范围预测", variable=self.pred_mode,
                        value="dates").pack(side=tk.LEFT, padx=5)

        self.days_frame = ttk.Frame(pred_frame)
        self.days_frame.pack(fill=tk.X, pady=5)

        ttk.Label(self.days_frame, text="预测天数:").pack(side=tk.LEFT, padx=5)
        self.pred_days_entry = ttk.Entry(self.days_frame, width=10)
        self.pred_days_entry.pack(side=tk.LEFT, padx=5)
        self.pred_days_entry.insert(0, "1825")  # 5年 = 1825天

        self.dates_frame = ttk.Frame(pred_frame)

        ttk.Label(self.dates_frame, text="开始日期:").pack(side=tk.LEFT, padx=5)
        self.start_date_entry = ttk.Entry(self.dates_frame, width=12)
        self.start_date_entry.pack(side=tk.LEFT, padx=5)

        ttk.Label(self.dates_frame, text="结束日期:").pack(side=tk.LEFT, padx=5)
        self.end_date_entry = ttk.Entry(self.dates_frame, width=12)
        self.end_date_entry.pack(side=tk.LEFT, padx=5)

        self.pred_mode.trace_add('write', self.toggle_prediction_mode)

        # 操作按钮
        action_frame = ttk.Frame(pred_frame)
        action_frame.pack(fill=tk.X, pady=10)

        ttk.Button(action_frame, text="开始预测",
                   command=self.run_prediction).pack(side=tk.LEFT, padx=5)
        ttk.Button(action_frame, text="重置参数",
                   command=self.clear_entries).pack(side=tk.LEFT, padx=5)
        ttk.Button(action_frame, text="查询亮度",
                   command=self.query_brightness).pack(side=tk.LEFT, padx=5)

        # 查询日期
        query_frame = ttk.Frame(pred_frame)
        query_frame.pack(fill=tk.X, pady=5)

        ttk.Label(query_frame, text="查询日期:").pack(side=tk.LEFT, padx=5)
        self.query_date_entry = ttk.Entry(query_frame, width=15)
        self.query_date_entry.pack(side=tk.LEFT, padx=5)
        self.query_date_entry.insert(0, datetime.now().strftime('%Y-%m-%d'))

        # 彗星轨道模拟
        orbit_sim_frame = ttk.LabelFrame(parent, text="彗星轨道模拟", padding="10")
        orbit_sim_frame.pack(fill=tk.BOTH, expand=True, pady=5)

        # 创建3D轨道图
        self.orbit_fig = plt.figure(figsize=(10, 8))
        self.orbit_ax = self.orbit_fig.add_subplot(111, projection='3d')
        self.orbit_canvas = FigureCanvasTkAgg(
            self.orbit_fig, master=orbit_sim_frame)
        self.orbit_canvas.get_tk_widget().pack(fill=tk.BOTH, expand=True)

        # 添加工具栏
        toolbar = NavigationToolbar2Tk(self.orbit_canvas, orbit_sim_frame)
        toolbar.update()

        # 控制面板
        control_frame = ttk.Frame(orbit_sim_frame)
        control_frame.pack(fill=tk.X, pady=5)

        # 行星显示控制
        self.planet_vars = {}
        for planet in self.planet_orbits:
            self.planet_vars[planet] = tk.BooleanVar(value=True)
            ttk.Checkbutton(control_frame, text=f"显示{planet}轨道",
                            variable=self.planet_vars[planet],
                            command=self.update_orbit_display).pack(side=tk.LEFT, padx=5)

        ttk.Button(control_frame, text="重置视图",
                   command=self.reset_orbit_view).pack(side=tk.LEFT, padx=5)
        ttk.Button(control_frame, text="放大海王星轨道",
                   command=self.zoom_neptune_orbit).pack(side=tk.LEFT, padx=5)

        # 初始化轨道显示
        self.init_orbit_display()

    def init_orbit_display(self):
        """初始化轨道显示"""
        self.orbit_ax.clear()

        # 设置初始视图
        self.orbit_ax.view_init(elev=30, azim=45)

        # 绘制太阳
        self.orbit_ax.plot([0], [0], [0], 'yo', markersize=10, label='太阳')

        # 绘制行星轨道
        self.draw_planet_orbits()

        # 设置标签和标题
        self.orbit_ax.set_xlabel('X (AU)')
        self.orbit_ax.set_ylabel('Y (AU)')
        self.orbit_ax.set_zlabel('Z (AU)')
        self.orbit_ax.set_title("太阳系行星轨道", fontsize=12)

        # 设置等比例
        self.set_equal_aspect()

        self.orbit_ax.legend()
        self.orbit_canvas.draw()

    def draw_planet_orbits(self):
        """绘制行星轨道"""
        theta = np.linspace(0, 2*np.pi, 100)

        for planet, radius in self.planet_orbits.items():
            if self.planet_vars[planet].get():
                x = radius * np.cos(theta)
                y = radius * np.sin(theta)
                z = np.zeros_like(theta)

                # 绘制轨道
                self.orbit_ax.plot(x, y, z, '--', color=self.planet_colors[planet],
                                   alpha=0.5, label=f'{planet}轨道')

                # 标记行星当前位置
                planet_idx = int(len(theta) * 0.25)  # 假设行星在1/4轨道位置
                self.orbit_ax.plot([x[planet_idx]], [y[planet_idx]], [z[planet_idx]],
                                   'o', color=self.planet_colors[planet],
                                   markersize=5, label=planet)

    def set_equal_aspect(self):
        """设置等比例视图"""
        try:
            self.orbit_ax.set_box_aspect([1, 1, 1])
        except AttributeError:
            # 兼容旧版本matplotlib
            max_range = max([np.ptp(self.orbit_ax.get_xlim()),
                             np.ptp(self.orbit_ax.get_ylim()),
                             np.ptp(self.orbit_ax.get_zlim())])
            mid_x = np.mean(self.orbit_ax.get_xlim())
            mid_y = np.mean(self.orbit_ax.get_ylim())
            mid_z = np.mean(self.orbit_ax.get_zlim())
            self.orbit_ax.set_xlim(mid_x - max_range/2, mid_x + max_range/2)
            self.orbit_ax.set_ylim(mid_y - max_range/2, mid_y + max_range/2)
            self.orbit_ax.set_zlim(mid_z - max_range/2, mid_z + max_range/2)

    def update_orbit_display(self):
        """更新轨道显示"""
        if (self.orbit_window is None or
                not self.orbit_window.winfo_exists()):
            return

        self.orbit_ax.clear()

        # 绘制太阳
        self.orbit_ax.plot([0], [0], [0], 'yo', markersize=10, label='太阳')

        # 绘制行星轨道
        self.draw_planet_orbits()

        # 绘制彗星轨道
        if self.orbit_points is not None:
            x, y, z = self.orbit_points.T
            self.orbit_ax.plot(x, y, z, 'b-', label='彗星轨道', linewidth=1)

            # 标记今日位置
            today = datetime.now().date()
            today_idx = None
            for i, date in enumerate(self.current_dates):
                if date.date() == today:
                    today_idx = i
                    break

            if today_idx is not None:
                today_x, today_y, today_z = x[today_idx], y[today_idx], z[today_idx]
                self.orbit_ax.plot([today_x], [today_y], [today_z], 'go',
                                   label=f'今日位置\n日彗距: {self.r_pred[today_idx]:.3f} AU\n地彗距: {self.delta_pred[today_idx]:.3f} AU')

            # 标记近日点
            peri_idx = np.argmin(np.linalg.norm(self.orbit_points, axis=1))
            peri_x, peri_y, peri_z = x[peri_idx], y[peri_idx], z[peri_idx]
            self.orbit_ax.plot([peri_x], [peri_y], [peri_z], 'ro',
                               label=f'近日点 ({self.r_pred[peri_idx]:.3f} AU)')

        # 设置标签和标题
        if self.orbit_points is not None:
            e = float(self.orbit_entries["eccentricity"].get())
            orbit_type = "椭圆" if e < 1 else "抛物线" if e == 1 else "双曲线"
            self.orbit_ax.set_title(
                f"{self.comet_var.get()}轨道模拟 ({orbit_type}轨道)", fontsize=12)
        else:
            self.orbit_ax.set_title("太阳系行星轨道", fontsize=12)

        self.orbit_ax.set_xlabel('X (AU)')
        self.orbit_ax.set_ylabel('Y (AU)')
        self.orbit_ax.set_zlabel('Z (AU)')

        # 设置等比例
        self.set_equal_aspect()

        self.orbit_ax.legend()
        self.orbit_canvas.draw()

    def reset_orbit_view(self):
        """重置3D轨道视图"""
        self.orbit_ax.view_init(elev=30, azim=45)
        self.set_equal_aspect()
        self.orbit_canvas.draw()

    def zoom_neptune_orbit(self):
        """放大海王星轨道"""
        neptune_radius = self.planet_orbits['海王星']
        zoom_range = neptune_radius * 1.2

        self.orbit_ax.set_xlim(-zoom_range, zoom_range)
        self.orbit_ax.set_ylim(-zoom_range, zoom_range)
        self.orbit_ax.set_zlim(-zoom_range, zoom_range)
        self.orbit_canvas.draw()

    def open_chart_window(self):
        """打开图表窗口"""
        if self.chart_window is None or not self.chart_window.winfo_exists():
            self.chart_window = tk.Toplevel(self.root)
            self.chart_window.title("彗星亮度图表")
            self.setup_chart_window()

            # 如果已有数据，立即绘制
            if self.current_dates is not None:
                self.update_chart_window()
        else:
            self.chart_window.lift()

    def open_orbit_window(self):
        """打开轨道窗口"""
        if self.orbit_window is None or not self.orbit_window.winfo_exists():
            self.orbit_window = tk.Toplevel(self.root)
            self.orbit_window.title("彗星轨道模拟")
            self.setup_orbit_window()

            # 如果已有数据，立即绘制
            if self.orbit_points is not None:
                self.update_orbit_window()
        else:
            self.orbit_window.lift()

    def close_all_windows(self):
        """关闭所有子窗口"""
        if self.chart_window is not None and self.chart_window.winfo_exists():
            self.chart_window.destroy()
        if self.orbit_window is not None and self.orbit_window.winfo_exists():
            self.orbit_window.destroy()

    def setup_chart_window(self):
        """设置图表窗口"""
        if not self.chart_window.winfo_exists():
            return

        self.chart_fig, (self.chart_ax1, self.chart_ax2) = plt.subplots(
            2, 1, figsize=(10, 8))
        self.chart_canvas = FigureCanvasTkAgg(
            self.chart_fig, master=self.chart_window)
        self.chart_canvas.get_tk_widget().pack(fill=tk.BOTH, expand=True)

        # 添加工具栏
        toolbar = NavigationToolbar2Tk(self.chart_canvas, self.chart_window)
        toolbar.update()

    def setup_orbit_window(self):
        """设置轨道窗口"""
        if not self.orbit_window.winfo_exists():
            return

        self.orbit_fig = plt.figure(figsize=(10, 8))
        self.orbit_ax = self.orbit_fig.add_subplot(111, projection='3d')
        self.orbit_canvas = FigureCanvasTkAgg(
            self.orbit_fig, master=self.orbit_window)
        self.orbit_canvas.get_tk_widget().pack(fill=tk.BOTH, expand=True)

        # 添加工具栏
        toolbar = NavigationToolbar2Tk(self.orbit_canvas, self.orbit_window)
        toolbar.update()

        # 控制面板
        control_frame = ttk.Frame(self.orbit_window)
        control_frame.pack(fill=tk.X, pady=5)

        # 行星显示控制
        self.planet_vars = {}
        for planet in self.planet_orbits:
            self.planet_vars[planet] = tk.BooleanVar(value=True)
            ttk.Checkbutton(control_frame, text=f"显示{planet}轨道",
                            variable=self.planet_vars[planet],
                            command=self.update_orbit_display).pack(side=tk.LEFT, padx=5)

        ttk.Button(control_frame, text="重置视图",
                   command=self.reset_orbit_view).pack(side=tk.LEFT, padx=5)
        ttk.Button(control_frame, text="放大海王星轨道",
                   command=self.zoom_neptune_orbit).pack(side=tk.LEFT, padx=5)

        # 初始化轨道显示
        self.init_orbit_display()

    def update_chart_window(self):
        """更新图表窗口内容 - 显示今日数据而非近日点数据"""
        if (self.chart_window is None or
            not self.chart_window.winfo_exists() or
                self.current_dates is None):
            return

        self.chart_ax1.clear()
        self.chart_ax2.clear()

        # 确定轨道类型
        e = float(self.orbit_entries["eccentricity"].get())
        if e < 1:
            orbit_type = "椭圆轨道"
        elif e == 1:
            orbit_type = "抛物线轨道"
        else:
            orbit_type = "双曲线轨道"

        # 绘制亮度曲线
        self.chart_ax1.plot(self.current_dates, self.orbit_m_pred, 'orange',
                            label='轨道计算', linewidth=2)
        self.chart_ax1.plot(self.current_dates, self.obs_m_pred, 'darkgreen',
                            label='观测拟合', linewidth=2)

        # 标记最亮点
        orbit_min_mag = min(self.orbit_m_pred)
        orbit_min_idx = np.argmin(self.orbit_m_pred)
        self.chart_ax1.plot(self.current_dates[orbit_min_idx], orbit_min_mag, 'o',
                            color='orange', markersize=8, label=f'轨道计算最亮: {orbit_min_mag:.2f}等')

        obs_min_mag = min(self.obs_m_pred)
        obs_min_idx = np.argmin(self.obs_m_pred)
        self.chart_ax1.plot(self.current_dates[obs_min_idx], obs_min_mag, 'o',
                            color='darkgreen', markersize=8, label=f'观测拟合最亮: {obs_min_mag:.2f}等')

        # 标记今日（10月11日）亮度
        today = datetime.now().date()
        today_idx = None
        for i, date in enumerate(self.current_dates):
            if date.date() == today:
                today_idx = i
                break

        if today_idx is not None:
            today_orbit_mag = self.orbit_m_pred[today_idx]
            today_obs_mag = self.obs_m_pred[today_idx]
            self.chart_ax1.plot(self.current_dates[today_idx], today_orbit_mag, 's', color='purple',
                                markersize=6, label=f'今日轨道计算: {today_orbit_mag:.2f}等')
            self.chart_ax1.plot(self.current_dates[today_idx], today_obs_mag, 's', color='cyan',
                                markersize=6, label=f'今日观测拟合: {today_obs_mag:.2f}等')

        self.chart_ax1.set_ylabel("视星等")
        self.chart_ax1.set_title(
            f"{self.comet_var.get()}亮度预测 - {orbit_type}", fontsize=12)
        self.chart_ax1.grid(True, alpha=0.3)
        self.chart_ax1.legend()
        self.chart_ax1.invert_yaxis()

        # 绘制距离曲线
        self.chart_ax2.plot(self.current_dates, self.r_pred,
                            'orange', label='日彗距', linewidth=2)
        self.chart_ax2.plot(self.current_dates, self.delta_pred, 'darkgreen',
                            label='地彗距', linewidth=2)

        # 标记今日（10月11日）距离
        if today_idx is not None:
            today_r = self.r_pred[today_idx]
            today_delta = self.delta_pred[today_idx]
            self.chart_ax2.plot(self.current_dates[today_idx], today_r, 's', color='purple',
                                markersize=6, label=f'今日日彗距: {today_r:.6f} AU')
            self.chart_ax2.plot(self.current_dates[today_idx], today_delta, 's', color='cyan',
                                markersize=6, label=f'今日地彗距: {today_delta:.6f} AU')

        # 标记近日点（12月16日）
        peri_date_str = self.orbit_entries["perihelion_time"].get()
        if peri_date_str:
            try:
                peri_date = datetime.strptime(
                    peri_date_str, "%Y-%m-%d %H:%M:%S").date()
                peri_idx = None
                for i, date in enumerate(self.current_dates):
                    if date.date() == peri_date:
                        peri_idx = i
                        break

                if peri_idx is not None:
                    peri_r = self.r_pred[peri_idx]
                    peri_delta = self.delta_pred[peri_idx]
                    self.chart_ax2.plot(self.current_dates[peri_idx], peri_r, 'D', color='red',
                                        markersize=6, label=f'近日点: {peri_r:.6f} AU')
                    self.chart_ax2.plot(self.current_dates[peri_idx], peri_delta, 'D', color='blue',
                                        markersize=6, label=f'近日点地彗距: {peri_delta:.6f} AU')
            except ValueError:
                pass

        self.chart_ax2.set_ylabel("距离 (AU)")
        self.chart_ax2.set_xlabel("日期")
        self.chart_ax2.grid(True, alpha=0.3)
        self.chart_ax2.legend()

        self.chart_fig.tight_layout()
        self.chart_canvas.draw()

    def on_comet_selected(self, event):
        """彗星选择事件处理"""
        comet_name = self.comet_var.get()
        self.fill_comet_data(comet_name)

    def fill_sample_data(self):
        """填充示例数据"""
        self.comet_var.set("323P-B/SOHO")
        self.fill_comet_data("323P-B/SOHO")

    def fill_comet_data(self, comet_name):
        """根据选择的彗星填充数据"""
        comet_data = {
            "323P-B/SOHO": {
                "name": "323P-B/SOHO",
                "orbit": {
                    "perihelion_distance": "0.040063",
                    "semi_major_axis": "2.890131",
                    "eccentricity": "0.986138",
                    "arg_perihelion": "353.9691",
                    "long_asc_node": "323.4650",
                    "inclination": "5.4627",
                    "orbital_period": "4.9135",
                    "perihelion_time": "2025-12-16 05:37:06",
                    "epoch_time": "2025-10-06"
                },
                "orbit_H": "20.0",
                "orbit_n": "10.0",
                "obs_H": "26.0",
                "obs_n": "4.0"
            },
            "240P/NEAT": {
                "name": "240P/NEAT",
                "orbit": {
                    "perihelion_distance": "2.121663",
                    "semi_major_axis": "3.860939",
                    "eccentricity": "0.450480",
                    "arg_perihelion": "352.0765",
                    "long_asc_node": "74.9114",
                    "inclination": "23.5370",
                    "orbital_period": "7.5868",
                    "perihelion_time": "2025-12-19 22:41:13",
                    "epoch_time": "2025-10-06"
                },
                "orbit_H": "11.3",
                "orbit_n": "2.0",
                "obs_H": "9.64",
                "obs_n": "10.0"
            },
            "24P/Schaumasse": {
                "name": "24P/Schaumasse",
                "orbit": {
                    "perihelion_distance": "1.183913",
                    "semi_major_axis": "4.058333",
                    "eccentricity": "0.708276",
                    "arg_perihelion": "58.4855",
                    "long_asc_node": "78.2724",
                    "inclination": "11.5023",
                    "orbital_period": "8.1760",
                    "perihelion_time": "2026-01-08 08:15:47",
                    "epoch_time": "2025-10-06"
                },
                "orbit_H": "6.5",
                "orbit_n": "35.0",
                "obs_H": "6.5",
                "obs_n": "14.0"
            },
            "C/2025 A6 (Lemmon)": {
                "name": "C/2025 A6 (Lemmon)",
                "orbit": {
                    "perihelion_distance": "0.529889",
                    "semi_major_axis": "121.283818",
                    "eccentricity": "0.995631",
                    "arg_perihelion": "132.9699",
                    "long_asc_node": "108.0978",
                    "inclination": "143.6635",
                    "orbital_period": "1335.7395",
                    "perihelion_time": "2025-11-08 12:53:59",
                    "epoch_time": "2025-10-04"
                },
                "orbit_H": "13.2",
                "orbit_n": "10",
                "obs_H": "6.9",
                "obs_n": "3.9"
            },
            "C/2025 R2 (SWAN)": {
                "name": "C/2025 R2 (SWAN)",
                "orbit": {
                    "perihelion_distance": "0.504053",
                    "semi_major_axis": "",
                    "eccentricity": "0.993413",
                    "arg_perihelion": "308.3194",
                    "long_asc_node": "335.3460",
                    "inclination": "4.4736",
                    "orbital_period": "",
                    "perihelion_time": "2025-09-12 19:55:55",
                    "epoch_time": "2025-10-04"
                },
                "orbit_H": "12.4",
                "orbit_n": "10",
                "obs_H": "8.8",
                "obs_n": "2.0"
            },
            "C/2025 K1 (ATLAS)": {
                "name": "C/2025 K1 (ATLAS)",
                "orbit": {
                    "perihelion_distance": "0.334197",
                    "semi_major_axis": "",
                    "eccentricity": "1.000263",
                    "arg_perihelion": "271.0256",
                    "long_asc_node": "97.5572",
                    "inclination": "147.8645",
                    "orbital_period": "",
                    "perihelion_time": "2025-10-08 10:31:34",
                    "epoch_time": "2025-10-04"
                },
                "orbit_H": "12.2",
                "orbit_n": "10",
                "obs_H": "12.4",
                "obs_n": "3.0"
            }
        }

        if comet_name in comet_data:
            data = comet_data[comet_name]
            self.clear_entries()

            # 填充彗星名称
            self.name_entry.insert(0, data["name"])

            # 填充轨道参数
            for key, value in data["orbit"].items():
                if value:
                    self.orbit_entries[key].insert(0, value)

            # 如果半长轴为空，自动计算
            if not data["orbit"]["semi_major_axis"]:
                q = float(data["orbit"]["perihelion_distance"])
                e = float(data["orbit"]["eccentricity"])
                a = self.calculate_semi_major_axis(q, e)
                self.orbit_entries["semi_major_axis"].insert(0, f"{a:.6f}")

            # 填充星等参数
            self.orbit_H_entry.insert(0, data["orbit_H"])
            self.orbit_n_entry.insert(0, data["orbit_n"])
            self.obs_H_entry.insert(0, data["obs_H"])
            self.obs_n_entry.insert(0, data["obs_n"])

    def calculate_semi_major_axis(self, q, e):
        """计算半长轴（处理非周期彗星）"""
        if e < 1:
            return q / (1 - e)
        elif e == 1:
            return 1e10  # 使用极大值代表无穷大
        else:
            return q / (1 - e)

    def clear_entries(self):
        """清空所有输入框"""
        if hasattr(self, 'name_entry') and self.name_entry.winfo_exists():
            self.name_entry.delete(0, tk.END)

        for key, entry in self.orbit_entries.items():
            if entry.winfo_exists():
                entry.delete(0, tk.END)

        if hasattr(self, 'orbit_H_entry') and self.orbit_H_entry.winfo_exists():
            self.orbit_H_entry.delete(0, tk.END)
            self.orbit_n_entry.delete(0, tk.END)
            self.obs_H_entry.delete(0, tk.END)
            self.obs_n_entry.delete(0, tk.END)
            self.query_date_entry.delete(0, tk.END)

        # 更新结果显示
        for label in self.info_labels.values():
            label.config(text="待计算")

    def validate_inputs(self):
        """验证输入数据"""
        try:
            # 获取基本输入
            comet_name = self.name_entry.get().strip()
            if not comet_name:
                raise ValueError("请输入彗星名称")

            # 获取轨道参数
            q = float(self.orbit_entries["perihelion_distance"].get())
            e = float(self.orbit_entries["eccentricity"].get())
            peri_time_str = self.orbit_entries["perihelion_time"].get()

            # 计算半长轴（处理非周期彗星）
            a_str = self.orbit_entries["semi_major_axis"].get()
            if a_str:
                a = float(a_str)
            else:
                a = self.calculate_semi_major_axis(q, e)

            # 获取轨道计算参数
            orbit_H = float(self.orbit_H_entry.get())
            orbit_n = float(self.orbit_n_entry.get())

            # 获取观测拟合参数
            obs_H = float(self.obs_H_entry.get())
            obs_n = float(self.obs_n_entry.get())

            # 验证参数范围
            if not 0.001 <= q <= 1000:
                raise ValueError("近日点距离应在0.001-1000AU范围内")
            if e < 0:
                raise ValueError("偏心率不能为负")
            if not -50 <= orbit_H <= 5000 or not -50 <= obs_H <= 5000:
                raise ValueError("绝对星等应在-50到5000范围内")
            if not -50 <= orbit_n <= 5000 or not -50 <= obs_n <= 5000:
                raise ValueError("斜率参数应在-50到5000范围内")

            # 解析近日点时间
            peri_date = datetime.strptime(peri_time_str, "%Y-%m-%d %H:%M:%S")

            return comet_name, q, a, e, peri_date, orbit_H, orbit_n, obs_H, obs_n

        except Exception as e:
            messagebox.showerror("输入错误", str(e))
            return None

    def query_brightness(self):
        """查询指定日期的亮度"""
        inputs = self.validate_inputs()
        if inputs is None:
            return

        comet_name, q, a, e, peri_date, orbit_H, orbit_n, obs_H, obs_n = inputs

        try:
            # 获取查询日期
            query_date_str = self.query_date_entry.get()
            query_date = datetime.strptime(query_date_str, '%Y-%m-%d')

            # 计算轨道距离
            days_from_peri = (query_date - peri_date).days

            if e < 1:
                # 椭圆轨道 - 使用完整的开普勒方程
                M = 2 * np.pi * days_from_peri / (a**1.5 * 365.25)
                E = self.solve_kepler_equation(M, e)
                r = a * (1 - e * np.cos(E))
            elif e == 1:
                # 抛物线轨道 - 使用精确计算
                r = self.calculate_parabolic_orbit(days_from_peri, q)
            else:
                # 双曲线轨道 - 使用完整算法
                r = self.calculate_hyperbolic_orbit(days_from_peri, q, e, a)

            # 计算地彗距
            delta = self.calculate_earth_distance(query_date, r, e, peri_date)

            # 计算星等
            orbit_m = orbit_H + 5 * \
                np.log10(delta) + 2.5 * orbit_n * np.log10(r)
            obs_m = obs_H + 5 * np.log10(delta) + 2.5 * obs_n * np.log10(r)

            # 计算彗发和彗尾长度
            coma_length_km, coma_length_deg, tail_length_km, tail_length_deg = self.calculate_coma_tail_length(
                r, delta)

            # 显示结果
            orbit_type = "椭圆" if e < 1 else "抛物线" if e == 1 else "双曲线"
            result_text = (
                f"彗星: {comet_name} ({orbit_type}轨道)\n"
                f"查询日期: {query_date_str}\n"
                f"日彗距: {r:.6f} AU\n"
                f"地彗距: {delta:.6f} AU\n"
                f"轨道计算预测: {orbit_m:.2f} 等\n"
                f"观测拟合预测: {obs_m:.2f} 等\n"
                f"亮度差异: {abs(orbit_m - obs_m):.2f} 等\n"
                f"彗发长度: {coma_length_km:.0f} km ({coma_length_deg:.4f}°)\n"
                f"彗尾长度: {tail_length_km:.0f} km ({tail_length_deg:.4f}°)"
            )
            messagebox.showinfo("查询结果", result_text)

        except Exception as e:
            messagebox.showerror("查询错误", str(e))

    def calculate_coma_tail_length(self, r, delta):
        """计算彗发和彗尾长度"""
        # 彗发长度（km） - 与距离太阳的距离成反比
        coma_length_km = 100000 / (r ** 0.5)

        # 彗尾长度（km） - 通常比彗发长
        tail_length_km = 1000000 / (r ** 0.5)

        # 转换为角直径（度）
        # 1 AU = 149,597,870.7 km
        au_to_km = 149597870.7
        delta_km = delta * au_to_km

        coma_length_deg = np.degrees(coma_length_km / delta_km)
        tail_length_deg = np.degrees(tail_length_km / delta_km)

        return coma_length_km, coma_length_deg, tail_length_km, tail_length_deg

    def solve_kepler_equation(self, M, e, tol=1e-8, max_iter=100):
        """解开普勒方程（椭圆轨道）"""
        if abs(M) < 1e-6:  # M接近0时直接返回
            return M

        # 初始猜测改进
        if e < 0.8:
            E = M
        else:
            E = np.pi if M > 0 else -np.pi

        for _ in range(max_iter):
            delta_E = (E - e * np.sin(E) - M) / (1 - e * np.cos(E))
            E -= delta_E

            if abs(E) > 10*np.pi:
                E = np.sign(E) * 10*np.pi

            if abs(delta_E) < tol:
                break

        return E

    def calculate_parabolic_orbit(self, days_from_peri, q):
        """计算抛物线轨道距离"""
        W = 3 * days_from_peri * np.sqrt(0.5 / (q**3)) / 2
        s = self.solve_cubic_equation(W)
        r = q * (1 + s**2)
        return max(r, 0.001)

    def solve_cubic_equation(self, W):
        """解三次方程 s + s^3/3 = W (抛物线轨道)"""
        s = W
        for _ in range(10):
            s_new = W - s**3 / 3
            if abs(s_new - s) < 1e-8:
                break
            s = s_new
        return s

    def calculate_hyperbolic_orbit(self, days_from_peri, q, e, a):
        """计算双曲线轨道距离"""
        N = 2 * np.pi * days_from_peri / ((-a)**1.5 * 365.25)
        H = self.solve_hyperbolic_kepler_equation(N, e)
        r = a * (1 - e * np.cosh(H))
        return max(r, 0.001)

    def solve_hyperbolic_kepler_equation(self, N, e, tol=1e-8, max_iter=100):
        """解双曲线开普勒方程"""
        if abs(N) < 0.1:
            H = N
        else:
            H = np.sign(N) * np.log(2*abs(N)/e + 1.8)

        for _ in range(max_iter):
            sinhH = np.sinh(H)
            coshH = np.cosh(H)

            f = e * sinhH - H - N
            df = e * coshH - 1

            if abs(df) < 1e-12:
                H += 0.1
                continue

            delta = f / df
            H -= delta

            if abs(H) > 100:
                H = np.sign(H) * 100

            if abs(delta) < tol:
                break

        return H

    def calculate_earth_distance(self, date, r, e, peri_date):
        """计算地彗距（考虑地球轨道位置）"""
        # 计算地球在轨道上的角度（简化模型）
        days_from_peri = (date - peri_date).days
        earth_angle = 2 * np.pi * (days_from_peri % 365.25) / 365.25

        # 地球位置（近似圆形轨道）
        earth_x = np.cos(earth_angle)
        earth_y = np.sin(earth_angle)

        # 彗星位置（考虑轨道倾角等）
        omega = np.radians(float(self.orbit_entries["arg_perihelion"].get()))
        Omega = np.radians(float(self.orbit_entries["long_asc_node"].get()))
        i = np.radians(float(self.orbit_entries["inclination"].get()))

        if e < 1:
            M = 2 * np.pi * days_from_peri / \
                (365.25 * float(self.orbit_entries["orbital_period"].get()))
            E = self.solve_kepler_equation(M, e)
            comet_x = r * (np.cos(Omega) * np.cos(omega + E) -
                           np.sin(Omega) * np.sin(omega + E) * np.cos(i))
            comet_y = r * (np.sin(Omega) * np.cos(omega + E) +
                           np.cos(Omega) * np.sin(omega + E) * np.cos(i))
        else:
            # 简化计算
            comet_x = r * np.cos(omega)
            comet_y = r * np.sin(omega) * np.cos(i)

        # 计算距离
        delta = np.sqrt((comet_x - earth_x)**2 + (comet_y - earth_y)**2)
        return max(delta, 0.001)

    def run_prediction(self):
        """运行亮度预测"""
        inputs = self.validate_inputs()
        if inputs is None:
            return

        comet_name, q, a, e, peri_date, orbit_H, orbit_n, obs_H, obs_n = inputs

        try:
            if self.pred_mode.get() == "days":
                future_days = int(self.pred_days_entry.get())
                if not 1 <= future_days <= 1000000:
                    raise ValueError("预测天数应在1-1000000范围内")

                # 生成时间序列（以近日点为中心）
                start_date = peri_date - timedelta(days=future_days//2)
                all_dates = [start_date +
                             timedelta(days=i) for i in range(future_days)]
            else:
                start_date_str = self.start_date_entry.get()
                end_date_str = self.end_date_entry.get()

                if not start_date_str or not end_date_str:
                    raise ValueError("请输入开始和结束日期")

                start_date = datetime.strptime(start_date_str, '%Y-%m-%d')
                end_date = datetime.strptime(end_date_str, '%Y-%m-%d')

                if start_date >= end_date:
                    raise ValueError("结束日期必须晚于开始日期")

                delta_days = (end_date - start_date).days
                if delta_days > 1000000:
                    raise ValueError("预测范围不能超过1000000天")

                all_dates = [start_date +
                             timedelta(days=i) for i in range(delta_days + 1)]

            # 确保包含今天（10月11日）的日期
            today = datetime.now().date()
            if today < all_dates[0].date() or today > all_dates[-1].date():
                messagebox.showwarning("日期范围警告", "预测范围不包含今天（10月11日）的日期")

            # 计算轨道距离
            r_pred = []
            for date in all_dates:
                days_from_peri = (date - peri_date).days

                if e < 1:
                    M = 2 * np.pi * days_from_peri / (a**1.5 * 365.25)
                    E = self.solve_kepler_equation(M, e)
                    r = a * (1 - e * np.cos(E))
                elif e == 1:
                    r = self.calculate_parabolic_orbit(days_from_peri, q)
                else:
                    r = self.calculate_hyperbolic_orbit(
                        days_from_peri, q, e, a)

                r_pred.append(max(r, 0.001))

            r_pred = np.array(r_pred)

            # 计算地彗距
            delta_pred = []
            for i, date in enumerate(all_dates):
                delta = self.calculate_earth_distance(
                    date, r_pred[i], e, peri_date)
                delta_pred.append(delta)
            delta_pred = np.array(delta_pred)

            # 计算星等
            orbit_m_pred = orbit_H + 5 * \
                np.log10(delta_pred) + 2.5 * orbit_n * np.log10(r_pred)
            obs_m_pred = obs_H + 5 * \
                np.log10(delta_pred) + 2.5 * obs_n * np.log10(r_pred)

            # 应用物理约束
            orbit_m_pred = np.clip(orbit_m_pred, -100, 5000)
            obs_m_pred = np.clip(obs_m_pred, -100, 5000)

            # 存储当前数据
            self.current_dates = all_dates
            self.orbit_m_pred = orbit_m_pred
            self.obs_m_pred = obs_m_pred
            self.r_pred = r_pred
            self.delta_pred = delta_pred

            # 运行轨道模拟
            self.run_orbit_simulation()

            # 绘制图表
            self.update_chart_window()

            # 更新结果信息
            self.update_results(comet_name, e, orbit_m_pred,
                                obs_m_pred, all_dates, r_pred, len(all_dates))

            messagebox.showinfo("预测完成", "彗星亮度预测计算完成！")

        except Exception as e:
            messagebox.showerror("预测错误", str(e))

    def run_orbit_simulation(self):
        """运行轨道模拟 - 5年时间范围"""
        inputs = self.validate_inputs()
        if inputs is None:
            return

        comet_name, q, a, e, peri_date, orbit_H, orbit_n, obs_H, obs_n = inputs

        try:
            num_points = 1000
            sim_years = 5  # 5年时间范围

            days_range = sim_years * 365.25
            start_date = peri_date - timedelta(days=days_range/2)
            end_date = peri_date + timedelta(days=days_range/2)

            dates = [start_date + timedelta(days=i*days_range/num_points)
                     for i in range(num_points)]

            positions = []
            for date in dates:
                days_from_peri = (date - peri_date).days

                if e < 1:
                    M = 2 * np.pi * days_from_peri / (a**1.5 * 365.25)
                    E = self.solve_kepler_equation(M, e)
                    r = a * (1 - e * np.cos(E))
                elif e == 1:
                    r = self.calculate_parabolic_orbit(days_from_peri, q)
                else:
                    r = self.calculate_hyperbolic_orbit(
                        days_from_peri, q, e, a)

                omega = np.radians(
                    float(self.orbit_entries["arg_perihelion"].get()))
                Omega = np.radians(
                    float(self.orbit_entries["long_asc_node"].get()))
                i = np.radians(float(self.orbit_entries["inclination"].get()))

                if e < 1:
                    E_val = self.solve_kepler_equation(
                        2 * np.pi * days_from_peri / (a**1.5 * 365.25), e)
                    x = r * (np.cos(Omega) * np.cos(omega + E_val) -
                             np.sin(Omega) * np.sin(omega + E_val) * np.cos(i))
                    y = r * (np.sin(Omega) * np.cos(omega + E_val) +
                             np.cos(Omega) * np.sin(omega + E_val) * np.cos(i))
                    z = r * np.sin(omega + E_val) * np.sin(i)
                else:
                    theta = 2 * np.pi * days_from_peri / 365.25
                    x = r * np.cos(theta)
                    y = r * np.sin(theta) * np.cos(i)
                    z = r * np.sin(theta) * np.sin(i)

                positions.append([x, y, z])

            self.orbit_points = np.array(positions)

            # 更新轨道显示
            self.update_orbit_display()

        except Exception as e:
            messagebox.showerror("轨道模拟错误", str(e))

    def toggle_prediction_mode(self, *args):
        """切换预测模式显示"""
        if self.pred_mode.get() == "days":
            self.days_frame.pack(fill=tk.X, pady=5)
            self.dates_frame.pack_forget()
        else:
            self.days_frame.pack_forget()
            self.dates_frame.pack(fill=tk.X, pady=5)

            # 自动填充默认日期范围（5年）
            if not self.start_date_entry.get():
                default_start = datetime.now().strftime('%Y-%m-%d')
                self.start_date_entry.insert(0, default_start)
            if not self.end_date_entry.get():
                default_end = (datetime.now() +
                               timedelta(days=1825)).strftime('%Y-%m-%d')
                self.end_date_entry.insert(0, default_end)

    def update_results(self, comet_name, e, orbit_m_pred, obs_m_pred, all_dates, r_pred, total_days):
        """更新预测结果信息"""
        # 确定轨道类型
        if e < 1:
            orbit_type = f"椭圆轨道 (e={e:.6f})"
        elif e == 1:
            orbit_type = "抛物线轨道 (e=1.000000)"
        else:
            orbit_type = f"双曲线轨道 (e={e:.6f})"

        # 轨道计算结果
        orbit_min_mag = min(orbit_m_pred)
        orbit_min_idx = np.argmin(orbit_m_pred)
        orbit_min_date = all_dates[orbit_min_idx].strftime('%Y-%m-%d')

        # 观测拟合结果
        obs_min_mag = min(obs_m_pred)
        obs_min_idx = np.argmin(obs_m_pred)
        obs_min_date = all_dates[obs_min_idx].strftime('%Y-%m-%d')

        # 亮度差异
        mag_diff = abs(orbit_min_mag - obs_min_mag)

        # 查找近日点
        peri_idx = np.argmin(r_pred)
        peri_date = all_dates[peri_idx].strftime('%Y-%m-%d')
        peri_dist = r_pred[peri_idx]

        # 查找今日（10月11日）数据
        today = datetime.now().date()
        today_idx = None
        today_orbit_mag = "N/A"
        today_obs_mag = "N/A"
        today_r = "N/A"
        today_delta = "N/A"

        for i, date in enumerate(all_dates):
            if date.date() == today:
                today_idx = i
                today_orbit_mag = orbit_m_pred[i]
                today_obs_mag = obs_m_pred[i]
                today_r = r_pred[i]
                today_delta = self.delta_pred[i]
                break

        # 计算彗发和彗尾长度
        if today_idx is not None:
            coma_length_km, coma_length_deg, tail_length_km, tail_length_deg = self.calculate_coma_tail_length(
                today_r, today_delta)
        else:
            coma_length_km = coma_length_deg = tail_length_km = tail_length_deg = "N/A"

        # 更新界面显示
        self.info_labels["轨道类型"].config(text=orbit_type)
        self.info_labels["轨道计算最亮星等"].config(text=f"{orbit_min_mag:.2f}")
        self.info_labels["轨道计算最亮日期"].config(text=orbit_min_date)
        self.info_labels["观测拟合最亮星等"].config(text=f"{obs_min_mag:.2f}")
        self.info_labels["观测拟合最亮日期"].config(text=obs_min_date)
        self.info_labels["近日点日期"].config(text=peri_date)
        self.info_labels["亮度差异"].config(text=f"{mag_diff:.2f} 等")
        self.info_labels["预测总天数"].config(text=f"{total_days:,} 天")
        self.info_labels["近地点距离"].config(text=f"{peri_dist:.6f} AU")
        self.info_labels["今日轨道计算星等"].config(
            text=f"{today_orbit_mag:.2f}" if today_idx is not None else "N/A")
        self.info_labels["今日观测拟合星等"].config(
            text=f"{today_obs_mag:.2f}" if today_idx is not None else "N/A")
        self.info_labels["今日日彗距"].config(
            text=f"{today_r:.6f}" if today_idx is not None else "N/A")
        self.info_labels["今日地彗距"].config(
            text=f"{today_delta:.6f}" if today_idx is not None else "N/A")
        self.info_labels["彗发长度 (km)"].config(
            text=f"{coma_length_km:.0f}" if today_idx is not None else "N/A")
        self.info_labels["彗发长度 (°)"].config(
            text=f"{coma_length_deg:.4f}" if today_idx is not None else "N/A")
        self.info_labels["彗尾长度 (km)"].config(
            text=f"{tail_length_km:.0f}" if today_idx is not None else "N/A")
        self.info_labels["彗尾长度 (°)"].config(
            text=f"{tail_length_deg:.4f}" if today_idx is not None else "N/A")
        self.root.update_idletasks()


# 主程序
if __name__ == "__main__":
    root = tk.Tk()
    app = CometBrightnessApp(root)
    root.mainloop()
